#include "my_background.h"
#include "sdkconfig.h"
#include <esp_log.h>
#include <mutex>


#define TAG "MyBackground"


MyBackground::MyBackground()
    : max_tasks_count_(0)
{

    // 创建事件组
    event_group_ = xEventGroupCreate();
    if (!event_group_) {
        ESP_LOGE(TAG, "Failed to crate event group.");
        return;
    }
    xEventGroupSetBits(event_group_, INSTANCE_ALIVED);

    // 创建后台管理任务
    auto result = xTaskCreatePinnedToCore(
        [](void* arg){
            auto* background = reinterpret_cast<MyBackground*>(arg);
            background->BackgroundHandler();
        },
        "Bg_Task",
        CONFIG_STACK_SIZE,
        this,
        CONFIG_BACKGROUND_TASKS_PRIORITY,
        &background_,
        CONFIG_CORE_ID == -1 ? tskNO_AFFINITY : CONFIG_CORE_ID
    );
    if (result != pdPASS) {
        ESP_LOGE(TAG, "Failed to create background manager task.");
        vEventGroupDelete(event_group_);
        event_group_ = nullptr;
        background_ = nullptr;
    }
}


MyBackground::~MyBackground()
{
    // 单例函数，不应该析构（除非是操作系统回收）
    if (event_group_) {
        vEventGroupDelete(event_group_);
    }
    if (background_) {
        vTaskDelete(background_);
    }
}

/// @brief 调度一个任务到后台运行
/// @param fn 任务函数
/// @param task_name 任务名
/// @param arg 任务函数参数
/// @param free_fn 任务清理时资源回收函数
/// @return 调度到后台队列成功返回true
bool MyBackground::Schedule(TaskWithArgFun fn, const std::string& task_name, void* arg, FreeFun free_fn) 
{
    if (!fn) {
        ESP_LOGW(TAG, "Attempt to schedule null task function.");
        return false;
    }
    std::lock_guard<std::mutex> lock(mutex_);
    if (task_list_.full()) {
        printf("Task buffer full, task dropped.\n");
        return false;
    } else {
        // ...
        // 注意：引用捕获在这里是安全的，因为：
        // 1. lambda 在 push_back 内部立即执行
        // 2. Task 构造函数拷贝所有数据
        // 3. 构造在函数返回前完成
        task_list_.construct([&task_name, &fn, &arg, &free_fn](Task* task){
            new (task) Task(task_name, fn, arg, free_fn);
        });
        // 计算更新最大任务数量
        auto count = task_list_.size();
        if ( count > max_tasks_count_ ) {
            max_tasks_count_ = count;
        }
        xEventGroupSetBits(event_group_, TASK_ARRIVED_EVENT);
    }

    return true;
}

/// @brief 调度一个任务到后台运行(无参数任务函数兼容版本，后续可能删除)
bool MyBackground::Schedule(TaskWithoutArgFun fn, const std::string& task_name) 
{
    if (!fn) {
        ESP_LOGW(TAG, "Attempt to schedule null task function.");
        return false;
    }
    auto function = [&fn](void*) { fn(); };
    return Schedule(function, task_name, nullptr, nullptr);
}

size_t MyBackground::Clear(const std::string& name)
{
    size_t count = 0;
    std::lock_guard<std::mutex> lock(mutex_);

    if (name.empty()) {
        count = task_list_.size();
        task_list_.clear();
    } else {
        task_list_.remove_if([name, &count](const Task& task){
            if (task.name == name) {
                count ++;
                return true;
            }
            return false;
        });
    }
    return count;
}

size_t MyBackground::GetBackgroundTasks() const
{
    std::lock_guard<std::mutex> lock(mutex_);
    return task_list_.size();
}


void MyBackground::PrintBackgroundInfo()
{
    Schedule([this](void* arg){
        if (max_tasks_count_ <= (CONFIG_MAX_BACKGROUND_TASKS >> 1)) {
            ESP_LOGI(TAG, "Max background tasks: %d", max_tasks_count_);
        } else if (max_tasks_count_ <= ((CONFIG_MAX_BACKGROUND_TASKS >> 1) + (CONFIG_MAX_BACKGROUND_TASKS >> 2))) {
            ESP_LOGW(TAG, "Max background tasks: %d", max_tasks_count_);
        } else {
            ESP_LOGE(TAG, "Max background tasks: %d", max_tasks_count_);
        }

        #ifdef CONFIG_FREERTOS_USE_STATS_FORMATTING_FUNCTIONS
            auto* task_list_buffer = new char[1024];
            vTaskList(task_list_buffer);

            printf("Name        State     Pri      Stack  Num\n");
            printf("-----------------------------------------\n");
            printf("%s\n", task_list_buffer);
            printf("help: X(Running) B(Blocked) R(Ready) D(Deleted) S(Suspended)\n");
            printf("  Pri:    Priority, higher value indicates higher priority.\n");
            printf("  Stack:  Mini remaining stack space during task execution (in words).\n");
            printf("  Num:    Task creation sequence number.\n");
            delete[] task_list_buffer;
        #endif
    }, "PrintBg");
}

/// @brief 后台管理任务
void MyBackground::BackgroundHandler()
{
    while(true) {

        // 等待任务到达后台事件
        xEventGroupWaitBits(event_group_, 
            TASK_ARRIVED_EVENT,
            pdTRUE,         // 清除事件
            pdFALSE,        // 等待任意一位
            portMAX_DELAY   // 持续等待
        );

        while (!task_list_.empty()) {
            task_list_.consume_front([](Task* task){
                task->execute();
            });
        }
    }
    ESP_LOGE(TAG, "Background manager task run out of range!");
    vTaskDelete(nullptr);
    background_ = nullptr;
}

